{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Programmation en Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Avertissement**\n", ">\n", "> Ce _notebook_ est directement inspir\u00e9 du fameux _wikibook_ \n", "> http://en.wikibooks.org/wiki/Python_Programming\n", "\n", "> **Convention**\n", "> \n", "> - Tous les noms de variable et les commentaires sont en *anglais*\n", "> - Le code est formatt\u00e9 suivant la PEP8 http://www.python.org/dev/peps/pep-0008/" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Introduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python est un langage *interpr\u00e9t\u00e9*, *dynamiquement*, *implicitement* et *fortement* typ\u00e9, utilis\u00e9 en administration syst\u00e8me, applications web, calcul scientifique, enseignement de l'algorithmique...\n", "\n", "Il est mutli-paradigme : *orient\u00e9 objet*, *imp\u00e9ratif* et *fonctionnel*.\n", "\n", "Cosm\u00e9tiquement, il se distingue d'autres langages par l'utilisation de l'indentation pour d\u00e9limiter les blocs.\n", "\n", "L'introduction se doit de commencer par le fameux:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print \"hello world\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Python 2 versus Python 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe deux versions majeurs de Python 2.7 et 3. La version 3 n'est pas compl\u00e8tement compatible avec la version 2.7, m\u00eame si un outil `2to3` permet une premi\u00e8re conversion na\u00efve automatique. Tous les modules majeurs ne sont pas encore compatible Python 3, cf. http://wiki.python.org/moin/Python2orPython3 pour le d\u00e9tail sur les difficult\u00e9s du passage de l'un \u00e0 l'autre." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Installation sous Linux" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python est g\u00e9n\u00e9ralement install\u00e9 sur toutes les bonnes distributions" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!which python" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!python --version" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\u00c9ventuellement, sous debian/ubuntu:\n", "\n", "`$ sudo apt-get install python2.7`\n", "\n", "ou\n", "\n", "`$ sudo apt-get install python3`\n" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Le mode int\u00e9ractif" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "D\u00e9marrons l'interp\u00e9teur pour enter en mode int\u00e9ractif, mode ou chaque instruction est execut\u00e9e \u00e0 la vol\u00e9e:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!python\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "5" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print 5*7" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "\"hello\" *4" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut \u00e9galement demander \u00e0 l'interpr\u00e9teur d'executer un script et de reprendre la main en fin de script" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%file /tmp/hello.py\n", "print 'hello world'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!python -i /tmp/hello.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ce qui peut \u00eatre tr\u00e8s utile pour le debug !" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Chercher de l'aide" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python int\u00e8gre la documentation de chaque fonction dans le code de la fonction elle m\u00eame, et fournit des outils pour manipuler ces informations, depuis l'interpr\u00e9teur ou le shell:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "help(len)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!pydoc str.startswith # \u00e9quivalent \u00e0 help(str.startswith)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "\u00c9xecuter un programme Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Reprenons le code du hello whorld \u00e9crit pr\u00e9c\u00e9demment" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!cat /tmp/hello.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est de bon ton de l'agr\u00e9menter d'un *shebang* appropri\u00e9:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%file /tmp/hello2.py\n", "#!/usr/bin/env python\n", "print \"hello world!\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut ensuite l'executer directement, apr\u00e8s lui avoir donn\u00e9 les bons droits:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%shell\n", "chmod u+x /tmp/hello2.py\n", "/tmp/hello2.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sinon, en utilisant l'interpr\u00e9teur standard:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!python /tmp/hello.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Bases du langage" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Variables et cha\u00eenes de caract\u00e8res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Au d\u00e9but \u00e9tait le n\u00e9ant:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print None, type(None)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En python, une variable est juste un identifiant attach\u00e9 \u00e0 une valeure quelconque, entier, flottant, cha\u00eene, dictionnaire, fonction ou tout autre objet :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "lucky = 7\n", "print lucky" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut changer le contenu d'une variable :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "lucky = 13\n", "print lucky" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ou son type, puisqu'une variable est juste une association identifiant <> valeur :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print lucky, type(lucky)\n", "lucky = \"7\"\n", "print lucky, type(lucky)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible d'associer la *valeur* d'une variable \u00e0 un nouveau nom. Elle est dans ce cas copi\u00e9e.\n", "\n", "> **Attention**\n", ">\n", "> la notion de copie d'une variable est diff\u00e9rente pour les types scalaires et les objets.\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "unlucky = 13\n", "print lucky, unlucky" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "lucky = unlucky\n", "print lucky, unlucky" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les cha\u00eenes de caract\u00e8res se d\u00e9crivent en utilisant les guillements simples, double ou les triples. Les simpels et doubles fonctionnent sur une ligne et sont interchangeables :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "sweet = \"cookie\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "sweeter = 'lollipop'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "sweetest = \"What about 'cookie' and \\\"lollipop\\\"?\"\n", "print sweetest" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "quote = '''\n", "Strange women lying in ponds\n", "distributing swords\n", "is no basis for a system of government!\n", "'''\n", "print quote\n", "\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La conversion d'entier en chaine n'est pas implicite :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\"1 + 1 = \" + 2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "\"1 + 1 = \" + str(2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Et \u00e0 l'inverse on peut convertire une cha\u00eene en entier :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "one = \"1\"\n", "print one, type(one)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "two = 2 * int(one)\n", "print two, type(two)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Un peu de math\u00e9matiques de base" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La formule pour convertir les kilos en pierre est redoutable :\n", "$$m_{stone} = \\frac{m_{kg} \\times 2.2}{14}$$\n", "\n", "Supposons que l'on nous donne une valeur en kilos :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "mass_kg = 42" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le calcul s'exprime assez naturellement sous la forme :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "mass_pound = mass_kg * 2.2 / 14" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ce qui nous offre l'occasion d'\u00e9crire notre premi\u00e8re fonction :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def kg_to_pound(mass_kg):\n", " return mass_kg * 2.2 / 14" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On notera l'utilisation de l'indentation pour d\u00e9limiter le corps de la fonction, \u00e0 opposer \u00e0 :\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def kg_to_pound(mass_kg):\n", "return mass_kg * 2.2 / 14" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible, si le corps de la fonction ne fait qu'une ligne, de tout mettre sur une ligne :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def kg_to_pound(mass_kg): return mass_kg * 2.2 / 14" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dans tous les cas, on peut appeler la fonction de fa\u00e7on assez conventionelle :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print kg_to_pound(12)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python offre de nombreux op\u00e9rateurs math\u00e9matiques :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a, b = 4, 3.\n", "print type(a), type(b)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print a + b # addition" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print a - b # substraction" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print a * b # multiplication" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print a / b # division" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print a // b # floor division" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a % b # modulo" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "-a # negation" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "abs(b) # absolute value" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "b**a # exponent" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La version _inplace_ des op\u00e9rateur \u00e9xiste \u00e9galement :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = 0 ; a += 2 ; a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a *= 3 ; a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a **= 2 ; a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "C'est le bon moment pour mettre en \u0153uvre nos premi\u00e8res connaissances sur un exercice d'une complexit\u00e9 \u00e0 coupler le souffle : le calcul du nombre de diagonales dans un polyn\u00f4mes.\n", "\n", "La formule donnant le nombre de diagonales $d$ en fonction du nombre de c\u00f4t\u00e9s $n$ est \n", "\n", "$$d = \\frac{n(n-3)}{2}$$\n", "\n", "1. tester cette formule pour diff\u00e9rentes valeurs de $n$ dans l'interpr\u00e9teur,\n", "2. \u00e9crivez dans l'interpr\u00e9teur la fonction \u00e9quivalente,\n", "3. appelez l\u00e0 depuis l'interpr\u00e9teur,\n", "4. sauvez l'ensemble dans un fichier, et chargez le fichier, avec l'option `-i` de l'interpr\u00e9teur." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Quelques remarques avant d'aller plus loin" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'usage de l'interpr\u00e9teur standard n'est pas des plus convivial, alros qu'il existe un interpr\u00e9teur avec des fonctionnalit\u00e9s avanc\u00e9es : `ipython`.\n", "\n", "Nous allos installer cet interpr\u00e9teur dans un environnement virtuel, a.k.a. `virtualenv`, qui permet de g\u00e9rer plusieurs version de python en parall\u00e8le." ] }, { "cell_type": "code", "collapsed": false, "input": [ "!virtualenv --no-site-packages /tmp/venv # creates a virtual environnment in /tmp/venv" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dans cet environnement virutel, on peut utiliser le syst\u00e8me de paquet python via la commande `pip` pour installer des outils suppl\u00e9mentaires. Il faut pour cela commencer par se placer dans l'environnement :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "! . /tmp/venv/bin/activate" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut ensuite utiliser la commande `pip` pour installer ipython" ] }, { "cell_type": "code", "collapsed": false, "input": [ "! pip install ipython" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Puis utiliser le nouvel interpr\u00e9teur :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "! ipython" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut quitter l'environnement virtuel \u00e0 tout moment en utilisant la commande `deactivate` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "! deactivate" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour suivre ce didacticiel dans de bonnes conditions, vous pouvez d'ores et d\u00e9j\u00e0 installer les modules suivant en t\u00e2che de fond :\n", "\n", "- `numpy` pour le calcul num\u00e9rique\n", "- `matplotlib` pour la visulatisation de donn\u00e9es\n", "- `scipy` pour le calcul scientifique de haut niveau\n", "\n", "Par ailleurs, on aura besoin des d\u00e9pendances suivantes pour d\u00e9couvrire les _notebooks_ de `ipython` :\n", "\n", "- `pyqt`\n", "- `pyzmq`\n", "- `tornado`\n", "- `ipython`\n", "- `pyside`" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Flot de contr\u00f4le" ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Tester" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La structure de contr\u00f4le principale pour le test est le `if`. Il cr\u00e9e un bloc et utilise donc l'indentation :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = 3\n", "if a % 2 == 1:\n", " print a, 'est impair'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "beaucoup de valeurs ont une conversion implicite pour le test :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print a, \"is evaluated as\",\n", "if a:\n", " print 'True'\n", "else:\n", " print 'False' " ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sinon, les op\u00e9rateurs de comparaison classiques fonctionnent \u00e0 merveille :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "1 > 2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1 < 2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1.5*10 == 15" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "0 | \"string\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "0 | bool(\"string\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1 & 2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1 and 2 # tricky" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "0 or \"string\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "x = 12\n", "0 <= x <= 1e10" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1<2<3<4<5<6" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "not 0" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "1 == 1. != 2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`None` vaut toujours `False` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if None: print 'Never, ever'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible d'imbriquer les tests :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if a < 0:\n", " print \"don't worry\"\n", "elif a > 0:\n", " print 'be happy'\n", "else:\n", " print 'neutral?'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Et bien s\u00fbr de faire une boucle _tant que_ bas\u00e9e sur une condition :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = 2 ** 4 + 3\n", "n = 0\n", "while a > 0:\n", " a = a / 2\n", " n = n + 1\n", "print n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. \u00c9crire une fonction prenant un argument et affichant un message \u00e0 l'\u00e9cran si cet argument est une puissance de 2. \n", "2. Il existe 4 entiers multiples de 3 ou 5 plus petits que 10 : 3, 5, 6, 9. Leur somme vaut 23; Combien vaut la somme de tous les multiples de 3 ou 5 plus petits que 1000 ? (cf. http://projecteuler.net/problem=1)" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Conteneurs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Un conteneur contient d'autres valeurs. En Python, les conteneurs ont une taille int\u00e9rogeable par la fonction `len` et on peut tester, avec un co\u00fbt plus ou moins grand, l'appartenance \u00e0 un conteneur avec le mot cl\u00e9 `in`." ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Listes / Tableaux" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En Python, la classe `list` permet de g\u00e9rer des tableaux de variables h\u00e9t\u00e9rog\u00e8nes (ou non) :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = [1,2, 3., True, \"False\"]\n", "print a" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[1, 2, 3.0, True, 'False']\n" ] } ], "prompt_number": 31 }, { "cell_type": "code", "collapsed": false, "input": [ "len(a)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 2, "text": [ "5" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "2 in a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 3, "text": [ "True" ] } ], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "5 not in a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 4, "text": [ "True" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Elles sont indi\u00e7ables \u00e0 partir de 0 :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[0]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "1" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comme un buffer (presque) circulaire :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[-1]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "'False'" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut extraire ou affecter des coupes :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[0:2]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "[1, 2]" ] } ], "prompt_number": 7 }, { "cell_type": "code", "collapsed": false, "input": [ "a[0:2] = [8,8]\n", "print a" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[8, 8, 3.0, True, 'False']\n" ] } ], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "a[::-1]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 9, "text": [ "['False', True, 3.0, 8, 8]" ] } ], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "a[1::2]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ "[8, True]" ] } ], "prompt_number": 11 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les listes sont construites par la fonction `list` ou par leur valeur litt\u00e9rale :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "b = list()\n", "c = [1]\n", "print b, c" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[] [1]\n" ] } ], "prompt_number": 25 }, { "cell_type": "code", "collapsed": false, "input": [ "[ a, b, [ [1], [2,3] ] ]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a + b + c" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 26, "text": [ "[1, 2, 3.0, True, 'False', 1]" ] } ], "prompt_number": 26 }, { "cell_type": "code", "collapsed": false, "input": [ "a * 3" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 29, "text": [ "[1, 2, 3.0, True, 'False', 1, 2, 3.0, True, 'False', 1, 2, 3.0, True, 'False']" ] } ], "prompt_number": 29 }, { "cell_type": "code", "collapsed": false, "input": [ "a - b" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for -: 'list' and 'list'", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma\u001b[0m \u001b[1;33m-\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for -: 'list' and 'list'" ] } ], "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si on connait \u00e0 l'avance le nombre d'\u00e9l\u00e9ments dans une liste, on peut faire du *d\u00e9paquetage* automatique :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "e, f, g, h, i = a\n", "print e,f,g,h,i" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1 2 3.0 True False\n" ] } ], "prompt_number": 32 }, { "cell_type": "code", "collapsed": false, "input": [ "e, r = [1,2,3]" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "too many values to unpack", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mValueError\u001b[0m: too many values to unpack" ] } ], "prompt_number": 33 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Tuples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les tuples sont semblables \u00e0 des listes immutables :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = (1,2,3., True, 'false')\n", "print a" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "(1, 2, 3.0, True, 'false')\n" ] } ], "prompt_number": 34 }, { "cell_type": "code", "collapsed": false, "input": [ "a[-1]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 35, "text": [ "'false'" ] } ], "prompt_number": 35 }, { "cell_type": "code", "collapsed": false, "input": [ "a[-1] = True" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mTrue\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ "(3 in a, True not in a)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 37, "text": [ "(True, False)" ] } ], "prompt_number": 37 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut cr\u00e9er un tuple vide \u00e0 l'aide de la fonction `tuple`, qui peut aussi transformer toute s\u00e9quence en tuple :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "tuple()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 38, "text": [ "()" ] } ], "prompt_number": 38 }, { "cell_type": "code", "collapsed": false, "input": [ "tuple([1,2,3])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 39, "text": [ "(1, 2, 3)" ] } ], "prompt_number": 39 }, { "cell_type": "code", "collapsed": false, "input": [ "(1,) * 2 + (2,)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 41, "text": [ "(1, 1, 2)" ] } ], "prompt_number": 41 }, { "cell_type": "code", "collapsed": false, "input": [ "('yeah',) + a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 42, "text": [ "('yeah', 1, 2, 3.0, True, 'false')" ] } ], "prompt_number": 42 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut parfois omettre les parenth\u00e8ses :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(a,b): return a,b\n", "e, f = 'e', 'f'" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 44 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Ensembles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les ensembles ne contiennent qu'une fois chaque valeur :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = { 1, 2, 'True', False , 1. }\n", "print a" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "set([False, 1.0, 2, 'True'])\n" ] } ], "prompt_number": 45 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le test d'appartenence est peu co\u00fbteux ($\\mathcal{O}(1)$) mais la syntax est la m\u00eame :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "{ 1 in a, 2. in a }" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 46, "text": [ "{True}" ] } ], "prompt_number": 46 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quelques op\u00e9rateurs sont support\u00e9s :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "b = { 2 , 1 }\n", "a + b" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for +: 'set' and 'set'", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mb\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m{\u001b[0m \u001b[1;36m2\u001b[0m \u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m}\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0ma\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'set' and 'set'" ] } ], "prompt_number": 52 }, { "cell_type": "code", "collapsed": false, "input": [ "print a, b\n", "a - b" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "set([False, 1.0, 2, 'True']) set([1, 2])\n" ] }, { "metadata": {}, "output_type": "pyout", "prompt_number": 53, "text": [ "{False, 'True'}" ] } ], "prompt_number": 53 }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'ensemble vide se cr\u00e9e _via_ la fonction `set`, pas `{}` qui est reserv\u00e9 aux dictionnaires :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "set() == {}" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 54, "text": [ "False" ] } ], "prompt_number": 54 }, { "cell_type": "code", "collapsed": false, "input": [ "type(set()), type({})" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 55, "text": [ "(set, dict)" ] } ], "prompt_number": 55 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Dictionnaires" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les dictionnaires contiennent des paires cl\u00e9 - valeur. Ce sont des tables de _hash_." ] }, { "cell_type": "code", "collapsed": false, "input": [ "d = { 1:'a', 2:'b', 3: 'c' }\n", "print d" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "{1: 'a', 2: 'b', 3: 'c'}\n" ] } ], "prompt_number": 56 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comme les autres conteneurs, ils peuvent contenir n'importe quel type de variables :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "{ 1: 'a', 'b' : 2 }" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 57, "text": [ "{1: 'a', 'b': 2}" ] } ], "prompt_number": 57 }, { "cell_type": "code", "collapsed": false, "input": [ "{ 1 : 'a', 1:'b'}" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 58, "text": [ "{1: 'b'}" ] } ], "prompt_number": 58 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut tester la pr\u00e9sence d'une clef, et extraire la valeur associ\u00e9e :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "{1 in d : d[3] }" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 60, "text": [ "{True: 'c'}" ] } ], "prompt_number": 60 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut ajouter des \u00e9l\u00e9ments par indicage :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "d[.1] = { 18 : 18 }\n", "print d" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "{1: 'a', 2: 'b', 3: 'c', 0.1: {18: 18}}\n" ] } ], "prompt_number": 61 }, { "cell_type": "code", "collapsed": false, "input": [ "len(d)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 62, "text": [ "4" ] } ], "prompt_number": 62 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Complexes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les nombres complexes sont des conteneurs un peu particulier :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "1 + 1j" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "c = 1j\n", "print c.real\n", "print c.imag" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "0.0\n", "1.0\n" ] } ], "prompt_number": 63 }, { "cell_type": "code", "collapsed": false, "input": [ "complex(1.3,3.1)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Boucles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les boucles en Python permettent uniquement d'it\u00e9rer sur des conteneurs :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for i in [1,2,3,True]:\n", " print type(i), i" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ " 1\n", " 2\n", " 3\n", " True\n" ] } ], "prompt_number": 64 }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'ordre n'est pas garanti pour les ensembles :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = { 5,4,3,3 }\n", "for i in a :\n", " print i" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "3\n", "4\n", "5\n" ] } ], "prompt_number": 65 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Et on it\u00e8re par d\u00e9faut sur les cl\u00e9s d'un dictionnaires :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = { 1: 'one', 2: 'two' }\n", "for i in a: print i," ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1 2\n" ] } ], "prompt_number": 66 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si besoin est, on peut cr\u00e9er des suites d'entiers avec la fonction `range` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "range(20)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 70, "text": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]" ] } ], "prompt_number": 70 }, { "cell_type": "code", "collapsed": false, "input": [ "for i in range(2, 20, 2):\n", " print i**2" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "4\n", "16\n", "36\n", "64\n", "100\n", "144\n", "196\n", "256\n", "324\n" ] } ], "prompt_number": 71 }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut aussi obtenir l'index de l'\u00e9l\u00e9ment \u00e0 chaque it\u00e9ration gr\u00e2ce \u00e0 la fonction `enumerate` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for i, v in enumerate(('True', False)):\n", " print 'index:', i, 'value:', v" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "index: 0 value: True\n", "index: 1 value: False\n" ] } ], "prompt_number": 72 }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Calculez la somme des nombres de fibonnaci *pairs* plus petits que 4 000 (cf. http://projecteuler.net/problem=2)\n", "2. Attaquez vous au probl\u00e8me http://projecteuler.net/problem=6" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Fonctions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les param\u00e8tres de fonction sont toujours pass\u00e9s **par copie** :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(a): a = 1\n", "a = 2\n", "foo(a)\n", "a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mais comme on peut renvoyer des tuples, il suffit g\u00e9n\u00e9ralement de renvoyer les nouvelles valeures, quelque soit leur nombre :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(a,b):\n", " c = a*b\n", " d = a+b\n", " e = a-b\n", " return c, d, e\n", "a = 2\n", "a, _, _ = foo(a,a)\n", "a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les arguments peuvent avoir des valeurs par d\u00e9faut :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def bar(guy = 'world'):\n", " print 'hello', guy\n", "bar()\n", "bar('trainees')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Attention**\n", "\n", "l'argument par d\u00e9faut est \u00e9valu\u00e9 une fois pour toute lors de la cr\u00e9ation de la fonction, un nouveau n'est pas cr\u00e9\u00e9 \u00e0 chaque appel" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def default(l=[]):\n", " l += [1]\n", " print l\n", " \n", "default()\n", "default()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python permet de s'affranchir de l'ordre des param\u00e8tres en les nommant au site d'appel :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def answer(the, question): return the + question\n", "some, stuff = 40, 2\n", "answer(question=some, the = stuff)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Une fonction acceptant n'importe quel nombre de param\u00e8tres non nomm\u00e9s utilisera l'\u00e9toile :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(*args):\n", " print type(args)\n", " print args\n", "foo()\n", "foo(1,2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Une fonctionnant acceptant n'importe quel param\u00e8tre nomm\u00e9 utilisera la double \u00e9toile :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def bar(**kwargs):\n", " print type(kwargs)\n", " print kwargs\n", "bar(am='stram', gram=1)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ce qui permet par exemple d'\u00e9crire une fonction qui fait suivre ses param\u00e8tres \u00e0 une autre, apr\u00e8s traitement :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def forward(*args, **kwargs):\n", " if 'sex' not in args and 'drug' not in kwargs:\n", " foo(*args)\n", " bar(**kwargs)\n", "forward(1,2,four=4)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Une fonction peut \u00eatre d\u00e9finie dans une autre fonction. Dans ce cas elle capture son contexte et peut y faire r\u00e9f\u00e9rence :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(x, y):\n", " def bar(z):\n", " return z + x\n", " return bar(1), bar(y)\n", "foo(1,2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les fonctions sont des variables comme les autres. Le nom des fonctions de base n'est pas r\u00e9serv\u00e9, on peut retourner des fonctions, les passer en param\u00e8tre etc." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def range():\n", " def bar(x,y): return x**y\n", " return bar" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est aussi possible de cr\u00e9er des fonctions anonymes :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def range():\n", " return lambda x,y: x**y\n", "range()(5,2,)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "range = lambda : lambda x,y: x**y\n", "range()(5,2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. \u00c9crire une impl\u00e9mentation na\u00efve de fibonnaci. Est il possible de l'\u00e9crire sous forme de lambda fonction ?\n", "2. \u00c9crire une fonction qui re\u00e7oit en param\u00e8tre une fonction et un param\u00e8tre, et qui applique cette fonction \u00e0 ce param\u00e8tre si ce param\u00e8tre s'\u00e9value \u00e0 `True`" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Les choses, les objets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python offre un paradigme objet. _Ad minima_, un objet est un ensemble de donn\u00e9es avec des fonctions associ\u00e9es. Vous en avez d\u00e9j\u00e0 manipul\u00e9 : les listes sont des objets.\n", "\n", "On ne manipule pas directement des objets, mais des r\u00e9f\u00e9rences (implicites) sur des objets. La m\u00e9moire associ\u00e9e est g\u00e9r\u00e9e par le rammase miette. Une des cons\u00e9quences est qu'on peut modifier le contenu d'un objet pass\u00e9 en param\u00e8tre de fonction (seule la r\u00e9f\u00e9rence est copi\u00e9e...) :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(a):\n", " a = a + [1]\n", "def bar(a):\n", " a += [1]\n", "l = list(enumerate('test'))\n", "print l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "foo(l)\n", "l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "bar(l)\n", "l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut tester si deux variables font r\u00e9f\u00e9rence au m\u00eame objet \u00e0 l'aide de l'op\u00e9rateur `is` ou de la fonction `id` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "id(l)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a, b = (l,l)\n", "id(a), id(b)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "a is b" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "c = list(b)\n", "a is c" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut acc\u00e9der aux variables membres d'un objet \u00e0 l'aide de l'op\u00e9rateur `.` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "type((1 + 2.5j).real)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "type(0j.conjugate)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Listes [bis]" ] }, { "cell_type": "code", "collapsed": false, "input": [ "l = list()\n", "l.append(1)\n", "l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.insert(0, 2)\n", "l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.extend([1,2,3])\n", "l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.count(1)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.index(3)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print l\n", "l.pop()\n", "print l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.pop(0)\n", "print l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.reverse()\n", "print l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "l.sort()\n", "print l" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Ensembles [bis]" ] }, { "cell_type": "code", "collapsed": false, "input": [ "s = set()\n", "s.add('1')\n", "print s" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "s.clear()\n", "print s" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "s.update(xrange(3))\n", "print s" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "s.difference({1})" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print s\n", "s.intersection({1})\n", "print s" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "{1}.issubset(s), s.issuperset({1})" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "{1}.isdisjoint({2})" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "{1,2}.symmetric_difference({2,3})" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Dictionnaire [bis]" ] }, { "cell_type": "code", "collapsed": false, "input": [ "d = { 'red': 'rouge', 'green': 'vert' }\n", "d.items()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "d.keys()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "d.values()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "dict.fromkeys(d.values())" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print d.get('yellow')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "print d.get('yellow', 'jaune')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "d.update([('blue', 'bleu'), ('black', 'noir')])\n", "print d" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Cr\u00e9er un dictionnaire contenant les 1000 premiers entiers en clef, et leur carr\u00e9 en valeur\n", "2. Impl\u00e9menter une fonction `count` qui prend en param\u00e8tre un conteneur (quelconque) et compte le nombre d'\u00e9l\u00e9ments diff\u00e9rents qu'elle contient. Testez l\u00e0 sur une liste, une cha\u00eene, un tuple...\n", "3. Utilisez un dictionnaire pour impl\u00e9menter une fonction `most_frequent_element` qui renvoie la valeur et l'index de l'\u00e9l\u00e9ment le plus fr\u00e9quent dans une liste." ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Les fichiers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les fichiers sont aussi une forme de conteneur. On les construit \u00e0 l'aide de la fonction `file` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fd = file('/tmp/data.txt', 'w')\n", "print type(fd)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut y \u00e9crire les donn\u00e9es une par une ou par paquet :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fd.write(str(3))\n", "fd.writelines(map(str,[4,5,6]))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comme en C (!) il faut fermer le fichier" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fd.close()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!cat /tmp/data.txt" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut \u00e9crire tout le fichier d'un coup :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "file('/tmp/data2.txt', 'w').write('\\n'.join(map(str, xrange(10))))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour ensuite le relire :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fd = open('/tmp/data2.txt')\n", "for line in fd.readlines():\n", " print line,\n", "fd.close()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "fd = file('/tmp/data2.txt')\n", "content = fd.read()\n", "fd.close()\n", "content" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. \u00c9crire et lire un fichier au format `.csv`" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Environnement logiciel, touche de style" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "D\u00e9verminage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python est fourni avec un d\u00e9boggueur rustique permettant une \u00e9valuation pas \u00e0 pas." ] }, { "cell_type": "code", "collapsed": false, "input": [ "!echo \"s = 5\" > /tmp/test.py\n", "!echo \"for i in range(s):\" >> /tmp/test.py\n", "!echo \" s += i\" >> /tmp/test.py\n", "!cat /tmp/test.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!pdb /tmp/test.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plusieurs commandes sont disponibles depuis l'interpr\u00e9teur :\n", "\n", "- `next` ou `n` pour passer \u00e0 l'instruction suivante,\n", "- `p` pour afficher le contenu d'une variable\n", "- `bt` pour inspecter la pile d'appel,\n", "- `up` pour remonter dans la pile d'appel,\n", "- `down` pour redescendre\n", "- `help` pour d\u00e9couvrire les autres\n", "\n", "On peut en outre executer n'importe quelle commande Python..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le _code snippet_ `import pdb ; pdb.set_trace()` permet aussi de psoitonner un point d'arr\u00eat n'importe o\u00f9 dans le programme..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On appr\u00e9ciera vite d'utiliser la version avec colorisation et compl\u00e9tion, `ipdb`, disponible _via_ `pip install`." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Mesures de performances" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour identifier les points chauds du programme, on peut utiliser les modules `profile` et `cProfile`" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!echo 'def fibo(n): return n if n <2 else fibo(n-1) + fibo(n-2)' > /tmp/fibo.py\n", "!echo 'print fibo(22)' >> /tmp/fibo.py\n", "!cat /tmp/fibo.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!python -m profile /tmp/fibo.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sous `ipython`, la commande magique `%timeit` est aussi particuli\u00e8rement utile..." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Style de codage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python favorise le code agr\u00e9able \u00e0 lire de haut niveau." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import this" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'outil `pep8` permet de v\u00e9rifier la claret\u00e9 du code utilis\u00e9:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!pep8 /tmp/fibo.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Documentation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plac\u00e9es judicieusement, les cha\u00eenes de caract\u00e8re font office de documentation et sont int\u00e9gr\u00e9es \u00e0 l'aide:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def foo(a):\n", " '''A useless function with a useless name.'''\n", " pass\n", "help(foo)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut \u00e9galement documenter les modules :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!PYTHONPATH=/tmp pydoc fibo" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "!sed -i -e '1 i \"The great fibonnaci function is among us\"' /tmp/fibo.py\n", "!PYTHONPATH=/tmp pydoc fibo" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Regroupez tous les exercices pr\u00e9c\u00e9dent se rapportant au projet euler dans un fichier `euler.py`.\n", "2. Documentez chacune des fonctions pour que `pydoc` puisse vous renseigner sur le probl\u00e8me en question.\n", "3. Profilez chacune des fonction et proposez des am\u00e9liorations le cas \u00e9ch\u00e9ant." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Constructions Avanc\u00e9es" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Les modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python est r\u00e9put\u00e9 pour sa biblioth\u00e8que standard, r\u00e9put\u00e9e pour \u00eatre \u00ab_battery included_\u00bb. On peut y acc\u00e9der \u00e0 travers l'importation de modules :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import math\n", "math.cos(3)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import math, cmath" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut importer un symbole particulier, \u00e9ventuellement en le renommant :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from random import randint, random\n", "randint(1,10), random()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "from cmath import sqrt as sqrt_with_complex\n", "sqrt_with_complex(-1)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le module `sys` est particuli\u00e8rement important puisqu'il permet d'acc\u00e9der aux arguments du programme :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__': # i.e. when the module is *not* imported but executed\n", " import sys\n", " print sys.argv" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Ajoutez un `main` \u00e0 `euler.py` qui permette de choisir le probl\u00e8me \u00e0 r\u00e9soudre \u00e0 partir d'un entier donn\u00e9 en ligne de commande" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Les classes utilisateurs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut d\u00e9finir une nouvelle classe avec le mot clef `class` :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Point:\n", " pass\n", "\n", "p = Point()\n", "print p, type(p)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut d\u00e9finir des m\u00e9thodes quelconques, qui se comportent comme des fonctions manipulant l'instance courante **pass\u00e9e en param\u00e8tre de la fonction** :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Baby:\n", " def cry(self, n=1):\n", " print \":'( \" * n\n", " \n", "baby = Baby()\n", "baby.cry()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les attributes de la classe sont ajout\u00e9s dynamiquement d\u00e8s qu'ils sont r\u00e9f\u00e9renc\u00e9s :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Mother:\n", " def work(self):\n", " self.tired = True\n", " def love(self, baby):\n", " if self.tired: print \"I always love\", baby\n", " else: print \"I love\", baby\n", " \n", "mum = Mother()\n", "mum.work()\n", "mum.love(baby)\n", " " ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe des m\u00e9thodes magiques, dont le nom prend un sens particulier:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Baby:\n", " def __str__(self): return \"mum's lovely baby\"\n", "baby = Baby()\n", "mum.love(baby)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La m\u00e9thode magique la plus connue est le constructeur :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Baby:\n", " def __init__(self, name):\n", " if not name:\n", " raise RuntimeError(\"All babies should have a name!\")\n", " self.name = name\n", " def __str__(self):\n", " return self.name\n", "\n", "tom = Baby('tom')\n", "str(tom)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe de nombreuses autres notions comme l'h\u00e9ritage (multiple), la fonction `super`, la classe `object`, les meta-classes..." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Compr\u00e9hension de liste / ensemble / dictionnaires" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python permet de construire facilement des s\u00e9quences \u00e0 partir d'autres s\u00e9quences :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = [1] * 10\n", "a[-2] *= 3\n", "print a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "[ x*x for x in a ]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "{ x*x for x in a } # <> set([x*x for x in a])" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "{ x: x*x for x in a} # <> dict([(x, x*x) for x in a])" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut \u00e9galement filtrer le contenu lors du parcours de la s\u00e9quence :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "[x for x in a if 0j] for j in xrange(5) ]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Proposez une solution \u00e0 http://projecteuler.net/problem=6 utilisant la compr\u00e9hension de liste. Int\u00e9grez l\u00e0 \u00e0 `euler.py` !\n", "2. Proposez une impl\u00e9mentation (sous forme de lambda !) de `count_uniq`, fonction qui compte le nombres d'\u00e9lements diff\u00e9rents dans une s\u00e9quence, bas\u00e9e sur la compr\u00e9hension d'ensembles." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "G\u00e9n\u00e9rateurs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction suivante ne termine jamais :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def bsd_rand(seed):\n", " l = []\n", " while True:\n", " seed = (1103515245*seed + 12345) & 0x7fffffff\n", " l.append(seed)\n", " return l " ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mais elle pourrait \u00eatre utile (c'est un g\u00e9n\u00e9rateur de nombres al\u00e9atoires par congruence lin\u00e9aire). Python permet de g\u00e9rer ce genre de probl\u00e8mes \u00e0 travers les *g\u00e9n\u00e9rateurs*.\n", "\n", "Un g\u00e9n\u00e9rateur est une fonction o\u00f9 le mot-clef `return` est remplac\u00e9 par `yield`. Au premier appel, elle renvoie un objet sur lequel on peut it\u00e9rer tant que le g\u00e9n\u00e9rateur n'est pas vid\u00e9, ce qui ne sera jamais le cas ici.\n", "\n", "Les deux fonctions associ\u00e9es au concept d'it\u00e9rateur utiles ici sont `iter` et `next`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "l = [1,2,4,8]\n", "i = iter(l)\n", "i" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(i)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(i)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(i)\n", "next(i)\n", "next(i)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction pr\u00e9c\u00e9dente peut \u00eatre convertie en g\u00e9n\u00e9rateur puis utilis\u00e9e de la m\u00eame fa\u00e7on :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def bsd_rand(seed):\n", " while True:\n", " seed = (1103515245*seed + 12345) & 0x7fffffff\n", " yield seed\n", " return # optional" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "r = bsd_rand(5)\n", "r" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(r)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(r)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "[ next(r)% 100 for x in xrange(10) ]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est \u00e9galement possible de faire de la compr\u00e9hension de liste _via_ un g\u00e9n\u00e9rateur. on \u00e9conomise alos l'espace de stockage de la liste:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = (x*x for x in xrange(1000000000000)) # very big but never actually created" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "next(a) ; next(a) ; next(a)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Exceptions et assertions" ] }, { "cell_type": "code", "collapsed": false, "input": [ "try:\n", " something = stupid # undefined variable\n", "except Exception as e:\n", " print e.args\n", " something = 'smart'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def fib(n):\n", " assert n >= 0 # disappears when compiled with -O\n", " return fibo(n)\n", "fib(-2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "def print_int(n):\n", " if type(n) is not int:\n", " raise RuntimeError(\"Expecting an integer\")\n", " print \"an int\", n\n", "print_int(3)\n", "print_int(3.)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Introspection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En Python, on peut inspecter dynamiquement l'\u00e9tat de tout objet. On peut obtenir la liste des m\u00e9thodes :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dir(list())" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La liste des variables locales ou globales :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "len(locals()), len(globals())" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut faire des choses comiques comme lire ou \u00e9crire les attributs :" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class List(list):pass\n", "l = List() ; l.append(1)\n", "getattr(l, \"__getitem__\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "try:l.smile()\n", "except: \"I don't know how to smile\" \n", "setattr(l, \"smile\", lambda : ':-)')\n", "l.smile()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Exercices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. En utilisant l'introspection, et en particulier la fonction `globals`, am\u00e9liorer le `main` de `euler.py` pour le rendre g\u00e9n\u00e9rique.\n", "2. Lisez la documentation de la fonction `eval` et imaginez le potentiel..." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Le mot de la fin: Tests en Python" ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Avec le module docstring" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def fact(n):\n", " '''\n", " computes n!\n", "\n", " >>> fact(3)\n", " 6\n", " '''\n", " return 1 if n == 0 else n * fact(n-1)\n", "\n", "import doctest\n", "doctest.run_docstring_examples(fact, globals(), verbose=True)\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Avec le module unittest" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import unittest\n", "class TestFact(unittest.TestCase):\n", " \n", " def test_zero(self):\n", " self.assertEqual(fact(0),1)\n", " \n", " def test_one(self):\n", " self.assertEqual(fact(1),1)\n", " \n", "suite = unittest.TestLoader().loadTestsFromTestCase(TestFact)\n", "unittest.TextTestRunner(verbosity=2).run(suite)" ], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }